#pragma once
#include <string.h>
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_check.h"
#include "es8311_reg.h"
#include "stdio.h"
extern esp_err_t es8311_register_read(uint8_t reg_addr, uint8_t *data, size_t len);
extern esp_err_t es8311_register_write_byte(uint8_t reg_addr, uint8_t data);

typedef enum es8311_resolution_t
{
    ES8311_RESOLUTION_16 = 16,
    ES8311_RESOLUTION_18 = 18,
    ES8311_RESOLUTION_20 = 20,
    ES8311_RESOLUTION_24 = 24,
    ES8311_RESOLUTION_32 = 32
} es8311_resolution_t;

typedef struct es8311_clock_config_t
{
    bool mclk_inverted;
    bool sclk_inverted;
    bool mclk_from_mclk_pin; // true: from MCLK pin (pin no. 2), false: from SCLK pin (pin no. 6)
    int mclk_frequency;      // This parameter is ignored if MCLK is taken from SCLK pin
    int sample_frequency;    // in Hz
    es8311_resolution_t res_in;
    es8311_resolution_t res_out;
} es8311_clock_config_t;

struct _coeff_div
{
    uint32_t mclk;     /* mclk frequency */
    uint32_t rate;     /* sample rate */
    uint8_t pre_div;   /* the pre divider with range from 1 to 8 */
    uint8_t pre_multi; /* the pre multiplier with 0: 1x, 1: 2x, 2: 4x, 3: 8x selection */
    uint8_t adc_div;   /* adcclk divider */
    uint8_t dac_div;   /* dacclk divider */
    uint8_t fs_mode;   /* double speed or single speed, =0, ss, =1, ds */
    uint8_t lrck_h;    /* adclrck divider and daclrck divider */
    uint8_t lrck_l;
    uint8_t bclk_div; /* sclk divider */
    uint8_t adc_osr;  /* adc osr */
    uint8_t dac_osr;  /* dac osr */
};

typedef enum
{
    ES8311_MIC_GAIN_MIN = -1,
    ES8311_MIC_GAIN_0DB,
    ES8311_MIC_GAIN_6DB,
    ES8311_MIC_GAIN_12DB,
    ES8311_MIC_GAIN_18DB,
    ES8311_MIC_GAIN_24DB,
    ES8311_MIC_GAIN_30DB,
    ES8311_MIC_GAIN_36DB,
    ES8311_MIC_GAIN_42DB,
    ES8311_MIC_GAIN_MAX
} es8311_mic_gain_t;

typedef enum
{
    ES8311_FADE_OFF = 0,
    ES8311_FADE_4LRCK, // 4LRCK means ramp 0.25dB/4LRCK
    ES8311_FADE_8LRCK,
    ES8311_FADE_16LRCK,
    ES8311_FADE_32LRCK,
    ES8311_FADE_64LRCK,
    ES8311_FADE_128LRCK,
    ES8311_FADE_256LRCK,
    ES8311_FADE_512LRCK,
    ES8311_FADE_1024LRCK,
    ES8311_FADE_2048LRCK,
    ES8311_FADE_4096LRCK,
    ES8311_FADE_8192LRCK,
    ES8311_FADE_16384LRCK,
    ES8311_FADE_32768LRCK,
    ES8311_FADE_65536LRCK
} es8311_fade_t;

esp_err_t es8311_init(es8311_clock_config_t *clk_cfg);

esp_err_t es8311_voice_volume_get(int *volume);
esp_err_t es8311_voice_volume_set(int volume, int *volume_set);

esp_err_t es8311_microphone_config(bool digital_mic);

esp_err_t es8311_sample_frequency_config(int mclk_frequency, int sample_frequency) ;
esp_err_t es8311_microphone_config(bool digital_mic);
esp_err_t es8311_voice_volume_set(int volume, int *volume_set);
esp_err_t es8311_voice_volume_get(int *volume);
esp_err_t es8311_voice_mute(bool mute);
esp_err_t es8311_microphone_gain_set(es8311_mic_gain_t gain_db);
esp_err_t es8311_voice_fade(const es8311_fade_t fade);
esp_err_t es8311_microphone_fade(const es8311_fade_t fade);
